package com.heima.media.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.common.dto.PageResponseResult;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.util.UserThreadLocalUtil;
import com.heima.media.dto.*;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmNewsMaterial;
import com.heima.media.entity.WmUser;
import com.heima.media.mapper.WmNewsMapper;
import com.heima.media.service.IAuditService;
import com.heima.media.service.IWmNewsMaterialService;
import com.heima.media.service.IWmNewsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.media.service.IWmUserService;
import com.heima.media.vo.WmNewsVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author lj
 * @since 2022-06-28
 */
@Slf4j
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements IWmNewsService {

    @Autowired
    private IWmNewsMaterialService wmNewsMaterialService;
    @Autowired
    private IAuditService auditService;
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;
    @Value("${topic.upDownTopic}")
    private String topicUpDownTopic;

    @Autowired
    private IWmUserService wmUserService;

    /**
     * 查询文章列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findPageByName(NewsAuthDto dto) {
        // 标题查询条件，状态，当前页码，页码大小
        String title = dto.getTitle();
        Integer status = dto.getStatus();
        Long page = dto.getPage();
        Integer size = dto.getSize();
        // 接收参数判断
        if (dto==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 条件构造器，思路锻造，先判断再构造
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        // 标题模糊查询
        if (title!=null) {
            queryWrapper.like(WmNews::getTitle,title);
        }
        // 状态查询
        if (status!=null) {
            queryWrapper.eq(WmNews::getStatus,status);
        }
        // 隐藏条件发布时间倒序
        queryWrapper.orderByDesc(WmNews::getPublishTime);
        // 分页条件构造
        Page<WmNews> iPage = new Page<>(page,size);
        // 返回分页结果集
        Page<WmNews> pageInfo = this.page(iPage, queryWrapper);
        return new PageResponseResult(page,size,pageInfo.getTotal(),pageInfo.getRecords());
    }

    /**
     * 查询文章详情，带回作者信息
     * @param id
     * @return
     */
    @Override
    public ResponseResult<WmNewsVo> findNewVoById(Integer id) {
        WmNews wmNews = this.getById(id);
        WmUser wmUser = wmUserService.getById(wmNews.getUserId());
        // 构造vo对象，添加作者名字
        WmNewsVo wmNewsVo = new WmNewsVo();
        BeanUtils.copyProperties(wmNews,wmNewsVo);
        wmNewsVo.setAuthorName(wmUser.getName());
        return ResponseResult.okResult(wmNewsVo);
    }

    /**
     * 人工审核
     * @param dto
     * @param type
     * @return
     */
    @Override
    public ResponseResult auth(NewsAuthDto dto, int type) {
        // type: 0驳回，1通过
        if (dto==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        WmNews wmNews = this.getById(dto.getId());
        // Status当前状态,0 草稿,1 提交（待审核）,2 审核失败,3 人工审核,4 人工审核通过,8 审核通过（待发布）,9 已发布
        if (type==0) {
            // 驳回
            wmNews.setStatus(2);
            wmNews.setReason(dto.getMsg());
        }else {
            // 审核通过
            Long articleId = auditService.saveArticle(wmNews);
            wmNews.setArticleId(articleId);
            wmNews.setStatus(4); // 审核通过后自动发布
        }
        // 更新自媒体文章信息
        this.updateById(wmNews);
        // 返回结果
        return ResponseResult.okResult();
    }

    /**
     * 自媒体图文信息列表查询
     * @param dto
     * @return
     */
    @Override
    public ResponseResult listByCondition(WmNewsPageDto dto) {
        log.info("[自媒体微服务======>自媒体图文信息列表查询实现类，接收参数：{}]",dto.toString());
        // 获取当前用户
        User user = UserThreadLocalUtil.get();
        if (user==null) {
            ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN); //未登录
        }
        // 当前接收对象判断
        if (dto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        // 条件构造器
        LambdaQueryWrapper<WmNews> queryWrapperWmNews = new LambdaQueryWrapper<>();
        // 状态判断
        if (dto.getStatus()!=null) {
            queryWrapperWmNews.eq(WmNews::getStatus,dto.getStatus());
        }
        // 关键字判断
        if (StringUtils.isNotBlank(dto.getKeyword())) {
            queryWrapperWmNews.like(WmNews::getTitle,dto.getKeyword());
        }
        // 频道判断
        if (dto.getChannelId()!=null) {
            queryWrapperWmNews.eq(WmNews::getChannelId,dto.getChannelId());
        }
        // 发布日期判断
        if (dto.getBeginPubDate()!=null) {
            queryWrapperWmNews.ge(WmNews::getPublishTime,dto.getBeginPubDate());
        }
        if (dto.getEndPubDate()!=null) {
            queryWrapperWmNews.le(WmNews::getPublishTime,dto.getEndPubDate());
        }

        // 隐藏条件
        queryWrapperWmNews.eq(WmNews::getUserId,user.getUserId());
        queryWrapperWmNews.orderByDesc(WmNews::getCreatedTime);

        // 分页条件
        Page<WmNews> page = new Page<>(dto.getPage(),dto.getSize());
        // 分页结果
        Page<WmNews> pageInfo = this.page(page, queryWrapperWmNews);

        // 返回结果集
        return new PageResponseResult(dto.getPage(),dto.getSize(),pageInfo.getTotal(),pageInfo.getRecords());
    }

    /**
     * 保存或修改文章
     * @param dto
     * @return
     */
    @Override
    public ResponseResult submit(WmNewsDto dto) {
        log.info("[自媒体微服务======>提交文章实现类，接收参数：{}]",dto.toString());
        // 业务分析，所用表：wm_news文章，wm_material素材，wm_news_material中间表
        // 获取当前用户
        User user = UserThreadLocalUtil.get();
        if (user==null) {
            ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN); //未登录
        }
        // 当前接收对象判断
        if (dto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 判断中间表id是否已经存在通过newsId来判断
        Integer newsId = dto.getId();
        // 存在删除
        if (newsId!=null) {
            // 直接通过userId删除
            LambdaQueryWrapper<WmNewsMaterial> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WmNewsMaterial::getNewsId,newsId);
            wmNewsMaterialService.remove(queryWrapper);
        }
        // 不存在保存或更新
        WmNews wmNews = new WmNews();
        // 设置值的过程
        BeanUtils.copyProperties(dto,wmNews);
        wmNews.setUserId(user.getUserId());
        wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());

        // wmNews.setType(); 封面这里要特别处理，封面：0 无图, 1 单图, 3 多图, -1 自动，格式注意：数据库中图片列表是多张图以逗号隔开
        // 图片保存，来源：images+content
        // 0 无图, 1 单图, 3 多图，只需要保存images，结合前端传来的数据进行处理，前端Json对象
        wmNews.setImages(JSON.toJSONString(dto.getImages()));
        // -1 自动，三种情况，无图，单图，三图，需要先从内容content中获取
        List<ImageDto> imageDtoContentList = getImages(dto.getContent());
        // 判断自动哪种情况：需要考虑图片数量，图片取值，注意，开整
        if (dto.getType()==-1) {
            // 判断
            int size = imageDtoContentList.size();
            if (size<=0){
                // 无图0
                wmNews.setType(0);
            }else if (size>0 && size<3){
                // 单图1
                wmNews.setType(1);
                // 动态截取，坐标固定，选取前面的几个
                // subList() 方法用于截取并返回动态数组中的一部分，[fromIndex,个数)
                List<ImageDto> imageDtoList = imageDtoContentList.subList(0, 1);
                wmNews.setImages(JSON.toJSONString(imageDtoList));
            }else {
                // 多图3
                wmNews.setType(3);
                // 动态截取，坐标固定，选取前面的几个
                // subList() 方法用于截取并返回动态数组中的一部分，[fromIndex,个数)
                List<ImageDto> imageDtoList = imageDtoContentList.subList(0, 3);
                wmNews.setImages(JSON.toJSONString(imageDtoList));
            }
        }
        // wmNews.setStatus(); 提交为1,草稿为0，无论提交还是草稿总要保存或更新
        // 文章更新或保存
        this.saveOrUpdate(wmNews);

        // 草稿不用保存中间表图与素材的关系，判断是否为保存
        if (dto.getStatus()==1) {
            // 保存中间表 文章内容与素材之间的关系，0内容
            saveRelation(imageDtoContentList,newsId,0);
            // 保存中间表 文章封面与素材之间的关系，1封面
            List<ImageDto> imageDtos = JSON.parseArray(wmNews.getImages(),ImageDto.class);
            saveRelation(imageDtos,newsId,1);

            // 自媒体文章审核
            auditService.audit(wmNews);
        }
        // 返回结果
        return ResponseResult.okResult();
    }

    /**
     * 自媒体端-文章的上架和下架
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        // 判断接收参数或者判断文章是否有文章id
        if (dto==null||dto.getId()==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 判断是否有登陆人
        User user = UserThreadLocalUtil.get();
        if (user==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        // 判断当前登陆人id与文章作者id是否相同，注意引用类型比较[-128,127]
        WmNews wmNews = this.getById(dto.getId());
        if (user.getUserId().intValue()!=wmNews.getUserId().intValue()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        if (wmNews==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 核心代码：上架状态 1 上架 0 下架 Boolean
        wmNews.setEnable(dto.getEnable()==1?true:false);
        this.updateById(wmNews);
        // 发送消息到kafka
        Map map = new HashMap();
        map.put("articleId",wmNews.getArticleId());
        map.put("enable",dto.getEnable()==1?true:false);
        kafkaTemplate.send(topicUpDownTopic,JSON.toJSONString(map));

        // 返回结果
        return ResponseResult.okResult();
    }

    /**
     * 保存中间表内容或封面图片和素材之间的关系
     * @param imageDtoList
     * @param newsId
     * @param type
     */
    private void saveRelation(List<ImageDto> imageDtoList, Integer newsId, int type) {
        int i = 0;
        for (ImageDto imageDto : imageDtoList) {
            WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
            wmNewsMaterial.setMaterialId(imageDto.getId());
            wmNewsMaterial.setNewsId(newsId);
            wmNewsMaterial.setType(type);
            wmNewsMaterial.setOrd(i++);
            wmNewsMaterialService.save(wmNewsMaterial);
        }
    }

    /**
     * 获取所有图片
     * @param content
     * @return
     */
    private List<ImageDto> getImages(String content) {
        List<ImageDto> imageDtoList = new ArrayList<>();
        // Json字符串转换，用alibaba.fastjson
        List<ContentDto> contentDtos = JSON.parseArray(content,ContentDto.class);
        for (ContentDto contentDto : contentDtos) {
            // 图片类型判断
            // 问题点：images×，image多了一个s，不报错，但测试结果就是不对，注意啦，前端数据格式！！！大招
            if (contentDto.getType().equals("image")) {
                ImageDto imageDto = new ImageDto();
                imageDto.setId(contentDto.getId());
                imageDto.setUrl(contentDto.getValue());
                imageDtoList.add(imageDto);
            }
        }
        return imageDtoList;
    }
}
